home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / Snippets / Devices / SCSI Simple Sample / Src / DoSCSICommandWithSense.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  4.9 KB  |  168 lines  |  [TEXT/KAHL]

  1. /*                            DoScsiCommandWithSense.c                            */
  2. /*
  3.  * DoScsiCommandWithSense.c
  4.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  * This is the common entry to the original and asynchronous SCSI Manager calls:
  7.  * if the asynchronous SCSI Manager is present, it calls it. If not present, it
  8.  * calls the original SCSI Manager and executes Request Sense if necessary.
  9.  */
  10. #include "SCSISimpleSample.h"
  11.  
  12. void                            IssueRequestSense(
  13.         register ScsiCmdBlockPtr    scsiCmdBlockPtr
  14.     );
  15.  
  16.  
  17. /*
  18.  * Do one SCSI Command. If the device returns Check Condition, issue Request Sense
  19.  * (original SCSI Manager only) and interpret the sense data. The original SCSI
  20.  * command status is in SCB.status. If it is statusErr or scsiNonZeroStatus,
  21.  * the sense data is in SCB.sense and the Request Sense status is in
  22.  * SCB.requestSenseStatus.
  23.  */
  24. void
  25. DoSCSICommandWithSense(
  26.         register ScsiCmdBlockPtr    scsiCmdBlockPtr,
  27.         Boolean                    displayError,
  28.         Boolean                    enableAsynchSCSI
  29.     )
  30. {
  31.         unsigned short            cmdBlockLength;
  32.         
  33. #define SCB    (*scsiCmdBlockPtr)
  34.         
  35.         /*
  36.          * Store the LUN information in the command block - this is needed
  37.          * for devices that only examine the command block for LUN values.
  38.          * (On SCSI-II, the asynchronous SCSI Manager also includes the
  39.          * LUN in the identify message).
  40.          */
  41.         SCB.command.scsi[1] &= ~0xE0;
  42.         SCB.command.scsi[1] |= (SCB.scsiDevice.LUN & 0x03) << 5;
  43.         cmdBlockLength = SCSIGetCommandLength((Ptr) &SCB.command);
  44.         /*
  45.          * Try to call SCSI Manager 4.3, if it fails with unimpErr, call
  46.          * the old SCSI Manager. Note: AsyncSCSI [in this instance]
  47.          * is synchronous. Real-world applications would use an asynchronous
  48.          * variant.
  49.          */
  50.         if (enableAsynchSCSI == FALSE || gEnableNewSCSIManager == FALSE)
  51.             SCB.status = unimpErr;                    /* Always original SCSI    */
  52.         else {
  53.             SCB.status = AsyncSCSI(
  54.                         SCB.scsiDevice,                /* Bus/target/LUN        */
  55.                         &SCB.command,                /* The command            */
  56.                         cmdBlockLength,                /* Command length        */
  57.                         SCB.writeToDevice,            /* TRUE if writing        */
  58.                         SCB.bufferPtr,                /* Data buffer, if any    */
  59.                         SCB.transferSize,            /* Data transfer length    */
  60.                         SCB.transferQuantum,        /* 1 means polled        */
  61.                         &SCB.sense,                    /* For sense result        */
  62.                         sizeof SCB.sense,            /* Sense buffer size    */
  63.                         kScsiSpinUpCompletionTime,    /* Watchdog timeout        */
  64.                         &SCB.statusByte,            /* Gets STS Phase byte    */
  65.                         &SCB.messageByte,            /* Gets MSG Completion    */
  66.                         &SCB.actualTransferCount    /* Bytes actually done    */
  67.                     );
  68.         }
  69.         if (SCB.status != unimpErr) {
  70.             /*
  71.              * The asynchronous SCSI Manager did something interesting.
  72.              */
  73.             switch (SCB.status) {
  74.             case noErr:
  75.                 break;
  76.             case scsiDeviceNotThere:
  77.             case scsiSelectTimeout:
  78.             case scsiBusInvalid:
  79.             case scsiTIDInvalid:
  80.                 /* These all mean "no such device" */
  81.                 break;
  82.             case statusErr:
  83.                 /*
  84.                  * Hmm. If the error is statusErr, the device returned
  85.                  * "Check Condition" and the SCSI Manager successfully
  86.                  * issued a Request Sense. We'll display the result of the
  87.                  * sense and update the spinUpState.
  88.                  */
  89.                 SCB.requestSenseStatus = noErr;
  90.                 if (displayError)
  91.                     ShowRequestSense(scsiCmdBlockPtr);
  92.                 break;
  93.             default:
  94.                 if (displayError)
  95.                     ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
  96.                 break;
  97.             }
  98.         }
  99.         else {
  100.             /*
  101.              * Call the original SCSI Manager.
  102.              */
  103.             SCB.status = OriginalSCSI(
  104.                         SCB.scsiDevice.targetID,
  105.                         &SCB.command,
  106.                         cmdBlockLength,
  107.                         SCB.writeToDevice,
  108.                         SCB.bufferPtr,
  109.                         SCB.transferSize,
  110.                         SCB.transferQuantum,
  111.                         kScsiSpinUpCompletionTime,
  112.                         &SCB.statusByte,
  113.                         &SCB.messageByte,
  114.                         &SCB.actualTransferCount
  115.                     );
  116.             if (SCB.status != noErr) {
  117.                 if (displayError)
  118.                     ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
  119.                 if (SCB.status == statusErr) {
  120.                     /*
  121.                      * Device returned "Check Condition."
  122.                      */
  123.                     IssueRequestSense(scsiCmdBlockPtr);
  124.                     if (displayError)
  125.                         ShowRequestSense(scsiCmdBlockPtr);
  126.                 }
  127.             }
  128.         }
  129. }
  130.  
  131. /*
  132.  * Execute "Get Extended Sense." This should not fail. This is only called by
  133.  * "old" SCSI Manager calls: the new SCSI Manager always enables "autosense."
  134.  */
  135. void
  136. IssueRequestSense(
  137.         register ScsiCmdBlockPtr    scsiCmdBlockPtr
  138.     )
  139. {
  140.         SCSI_6_Byte_Command        requestSense;
  141.         unsigned short            statusByte;                /* <- From Status Phase    */
  142.         unsigned short            messageByte;            /* <- From Msg Phase    */
  143.         unsigned long            actualTransferCount;
  144.         
  145.         CLEAR(requestSense);
  146.         requestSense.opcode = kScsiCmdRequestSense;
  147.         requestSense.len = sizeof SCB.sense;
  148.         /*
  149.          * Stuff the logical unit number into the command block.
  150.          */
  151.         requestSense.lbn3 &= 0xE0;
  152.         requestSense.lbn3 |= (SCB.scsiDevice.targetID & 0x03) << 5;
  153.         SCB.requestSenseStatus = OriginalSCSI(
  154.                     SCB.scsiDevice.targetID,
  155.                     (SCSI_CommandPtr) &requestSense,
  156.                     sizeof requestSense,
  157.                     FALSE,                                /* No write                */
  158.                     (Ptr) &SCB.sense,
  159.                     sizeof SCB.sense,
  160.                     1,
  161.                     kScsiSpinUpCompletionTime,
  162.                     &statusByte,
  163.                     &messageByte,
  164.                     &actualTransferCount
  165.                 );
  166. }
  167.  
  168.